package com.nth.android;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

/**
 * Title: AndroidFramework <br />
 * Copyright: Copyright (c) 2009 <br />
 * NTH Company: NTH d.o.o. <br />
 * 
 * @author Tomica Bosnjak
 * @version 1.0.0
 * @since 1.0.0
 */
public class CacheMap<E extends Object, F extends Object> extends LinkedHashMap<E, F> {

	private static final long serialVersionUID = 1246923607840597352L;

	private final int capacity;

	private long accessCount = 0;
	private long hitCount = 0;

	private final Object syncObject = new Object();

	/**
	 * 
	 * CacheMap initialization with defined capacity and
	 * default value for order mode set to true
	 * 
	 * @param capacity
	 */
	public CacheMap(int capacity) {
		this(capacity, true);
	}

	/**
	 * 
	 * CacheMap initialization with defined capacity and
	 * order mode
	 * 
	 * @param capacity
	 * @param orderMode
	 */
	public CacheMap(int capacity, boolean orderMode) {
		super(capacity, 1.1F, orderMode);
		this.capacity = capacity;
	}

	@Override
	public F put(E key, F value) {
		synchronized (syncObject) {
			return super.put(key, value);
		}
	}

	@Override
	public void putAll(Map<? extends E, ? extends F> map) {
		synchronized (syncObject) {
			super.putAll(map);
		}
	}

	@Override
	public F remove(Object key) {
		synchronized (syncObject) {
			return super.remove(key);
		}
	}

	@Override
	public void clear() {
		synchronized (syncObject) {
			super.clear();
		}
	}

	@Override
	public F get(Object key) {
		synchronized (syncObject) {
			accessCount++;
			if (containsKey(key)) {
				hitCount++;
			}

			return super.get(key);
		}
	}

	@Override
	public Set<E> keySet() {
		synchronized (syncObject) {
			return super.keySet();
		}
	}

	/**
	 * 
	 * getter method for accessCount variable
	 * 
	 * @return long
	 */
	public long getAccessCount() {
		synchronized (syncObject) {
			return accessCount;
		}
	}

	
	/**
	 * 
	 * getter method for hitCount variable
	 * 
	 * @return
	 */
	public long getHitCount() {
		synchronized (syncObject) {
			return hitCount;
		}
	}

	@Override
	public int size() {
		synchronized (syncObject) {
			return super.size();
		}
	}

	/**
	 * 
	 * getter method for cache map capacity
	 * 
	 * @return
	 */
	public int getCapacity() {
		return capacity;
	}

	@Override
	protected boolean removeEldestEntry(Entry<E, F> eldest) {
		synchronized (syncObject) {
			return super.size() > capacity;
		}
	}

	/**
	 * 
	 * getter method for sync object
	 * 
	 * @return Object
	 */
	public Object getSyncObject() {
		return syncObject;
	}

	@Override
	public String toString() {
		return CacheMap.class.getName() + ": [Size : " + size() + ", Capacity : " + capacity + "]";
	}
}